To define a new computational command which
takes and/or leaves arguments on the stack, a special form of
interactive clause is used.
(interactive num tag)
where num is an integer, and
tag is a string. The effect is to pop num
values off the stack, resimplify them by calling
calc-normalize, and hand them to your function
according to the function's argument list. Your function may
include &optional and &rest
parameters, so long as calling the function with num
parameters is valid.
Your function must return either a number or a formula in a
form acceptable to Calc, or a list of such numbers or formulas.
These value(s) are pushed onto the stack when the function
completes. They are also recorded in the Calc Trail buffer on a
line beginning with tag, a string of (normally) four
characters or less. If you omit tag or use
nil as a tag, the result is not recorded in the
trail.
As an example, the definition
(defmath myfact (n)
"Compute the factorial of the integer at the top of the stack."
(interactive 1 "fact")
(if (> n 0)
(* n (myfact (1- n)))
(and (= n 0) 1)))
is a version of the factorial function shown previously which can be used as a command as well as an algebraic function. It expands to
(defun calc-myfact ()
"Compute the factorial of the integer at the top of the stack."
(interactive)
(calc-slow-wrapper
(calc-enter-result 1 "fact"
(cons 'calcFunc-myfact (calc-top-list-n 1)))))
(defun calcFunc-myfact (n)
"Compute the factorial of the integer at the top of the stack."
(if (math-posp n)
(math-mul n (calcFunc-myfact (math-add n -1)))
(and (math-zerop n) 1)))
The
calc-slow-wrapper function is a version of
calc-wrapper that automatically puts up a
‘Working...’
message before the computation begins. (This message can be
turned off by the user with an m w
(calc-working) command.)
The
calc-top-list-n function returns a list of the
specified number of values from the top of the stack. It
resimplifies each value by calling calc-normalize.
If its argument is zero it returns an empty list. It does not
actually remove these values from the stack.
The
calc-enter-result function takes an integer
num and string tag as described above, plus
a third argument which is either a Calculator data object or a
list of such objects. These objects are resimplified and pushed
onto the stack after popping the specified number of values from
the stack. If tag is non-nil, the values
being pushed are also recorded in the trail.
Note that if calcFunc-myfact returns
nil this represents “leave the function in
symbolic form.” To return an actual empty list, in the
sense that calc-enter-result will push zero elements
back onto the stack, you should return the special value
‘'(nil)’, a
list containing the single symbol nil.
The interactive declaration can actually contain
a limited Emacs-style code string as well which comes just before
num and tag. Currently the only Emacs code
supported is ‘"p"’, as in
(defmath foo (a b &optional c)
(interactive "p" 2 "foo")
body)
In this example, the command calc-foo will
evaluate the expression ‘foo(a,b)’ if executed with no
argument, or ‘foo(a,b,n)’ if executed with a numeric
prefix argument of ‘n’.
The other code string allowed is ‘"m"’ (unrelated to the usual
‘"m"’ code as
used with defun). It uses the numeric prefix
argument as the number of objects to remove from the stack and
pass to the function. In this case, the integer num
serves as a default number of arguments to be used when no prefix
is supplied.